Diamanten#
Der folgende Datensatz enthält die Preise und Eigenschaften von Diamanten. Die Eigenschaften sind:
Preis (in US-Dollar)
Karatgewicht des Diamanten
Schliffqualität (befriedigend, gut, sehr gut, erstklassig, ideal)
Farbe des Diamanten (von J (schlechteste) bis D (beste))
Reinheit - ein Maß für die Klarheit des Diamanten (I1 (schlechteste), SI2, SI1, VS2, VS1, VVS2, VVS1, IF (beste))
x - Länge in mm
y - Breite in mm
z - Tiefe in mm
Gesamttiefe (in Prozent = z / Mittelwert (x, y) = 2 * z / (x + y))
Breite der Oberseite des Diamanten im Verhältnis zur breitesten Stelle
import pandas as pd
data = pd.read_csv('data/diamonds_DE.csv', skiprows=2)
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 53940 entries, 0 to 53939
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Unnamed: 0 53940 non-null int64
1 Karat 53940 non-null float64
2 Schliffqualitaet 53940 non-null object
3 Farbe 53940 non-null object
4 Reinheit 53940 non-null object
5 Tiefe 53940 non-null float64
6 Breite 53940 non-null float64
7 Preis 53940 non-null int64
8 x 53940 non-null float64
9 y 53940 non-null float64
10 z 53940 non-null float64
dtypes: float64(6), int64(2), object(3)
memory usage: 4.5+ MB
Der Datensatz enthält 53940 Einträge mit 11 Eigenschaften. Alle Einträge sind gültige Einträge. Die Eigenschaften ‘Unnamed: 0’ und ‘Preis’ sind Integers. Die Eigenschaften ‘Karat’, ‘Tiefe’, ‘Breite’, ‘x’, ‘y’ und ‘z’ sind Floats. Die Eigenschaften ‘Schliffqualitaet’, ‘Farbe’ und ‘Reinheit’ sind Objekte.
data.head()
| Unnamed: 0 | Karat | Schliffqualitaet | Farbe | Reinheit | Tiefe | Breite | Preis | x | y | z | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0.23 | ideal | E | SI2 | 61.5 | 55.0 | 326 | 3.95 | 3.98 | 2.43 |
| 1 | 2 | 0.21 | erstklassig | E | SI1 | 59.8 | 61.0 | 326 | 3.89 | 3.84 | 2.31 |
| 2 | 3 | 0.23 | gut | E | VS1 | 56.9 | 65.0 | 327 | 4.05 | 4.07 | 2.31 |
| 3 | 4 | 0.29 | erstklassig | I | VS2 | 62.4 | 58.0 | 334 | 4.20 | 4.23 | 2.63 |
| 4 | 5 | 0.31 | gut | J | SI2 | 63.3 | 58.0 | 335 | 4.34 | 4.35 | 2.75 |
Die ersten fünf Zeilen des Datensatzes legen nahe, dass die Eigenschaft ‘Unnamed: 0’ ein Index ist. Wir visualisieren diese Eigeschaft, um die Hypothese zu überprüfen.
import plotly.express as px
fig = px.scatter(data, y = 'Unnamed: 0',
title='Diamanten')
fig.show()
Tatsächlich stimmen (zumindest visuell) der automatisch erzeugte Index des DataFrame-Objektes und die Werte von ‘Unnamed: 0’ überein. Die überflüssige Spalte wird gelöscht.
data.drop(columns='Unnamed: 0', inplace=True)
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 53940 entries, 0 to 53939
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Karat 53940 non-null float64
1 Schliffqualitaet 53940 non-null object
2 Farbe 53940 non-null object
3 Reinheit 53940 non-null object
4 Tiefe 53940 non-null float64
5 Breite 53940 non-null float64
6 Preis 53940 non-null int64
7 x 53940 non-null float64
8 y 53940 non-null float64
9 z 53940 non-null float64
dtypes: float64(6), int64(1), object(3)
memory usage: 4.1+ MB
Als nächstes werden die Eigenschaften weiter analysiert. Um einfacher auf die Input-Eigenschaften zugreifen zu können, definieren wir zwei Listen. Die erste Liste enthält die numerischen Input-Eigenschaften, die zweite die kategorischen Input-Eigenschaften. Die Zielgröße, d.h. der Output, ist die Eigenschaft Preis.
input_numerical = ['Karat', 'Tiefe', 'Breite', 'x', 'y', 'z']
input_categorial = ['Schliffqualitaet', 'Farbe', 'Reinheit']
Die Übersicht der statistischen Kennzahlen zu den numerischen Input-Eigenschaften ist wie folgt:
data.describe()
| Karat | Tiefe | Breite | Preis | x | y | z | |
|---|---|---|---|---|---|---|---|
| count | 53940.000000 | 53940.000000 | 53940.000000 | 53940.000000 | 53940.000000 | 53940.000000 | 53940.000000 |
| mean | 0.797940 | 61.749405 | 57.457184 | 3932.799722 | 5.731157 | 5.734526 | 3.538734 |
| std | 0.474011 | 1.432621 | 2.234491 | 3989.439738 | 1.121761 | 1.142135 | 0.705699 |
| min | 0.200000 | 43.000000 | 43.000000 | 326.000000 | 0.000000 | 0.000000 | 0.000000 |
| 25% | 0.400000 | 61.000000 | 56.000000 | 950.000000 | 4.710000 | 4.720000 | 2.910000 |
| 50% | 0.700000 | 61.800000 | 57.000000 | 2401.000000 | 5.700000 | 5.710000 | 3.530000 |
| 75% | 1.040000 | 62.500000 | 59.000000 | 5324.250000 | 6.540000 | 6.540000 | 4.040000 |
| max | 5.010000 | 79.000000 | 95.000000 | 18823.000000 | 10.740000 | 58.900000 | 31.800000 |
fig = px.box(data, y = input_numerical,
title='Diamanten: numerische Eigenschaften',
labels={'variable': 'Eigenschaft', 'value': 'Wert'})
fig.show()
Die Eigenschaft Karat unterscheidet sich in der Größenordnung von den beiden Eigenschaften Tiefe und Breite sowie x, y, und z. Diese drei Gruppen werden jetzt einzeln untersucht.
fig = px.box(data, y = 'Karat',
title='Diamanten')
fig.show()
75 % der Diamanten haben ein Karat und weniger, wobei der Median bei 0.7 Karat liegt. Das ist etwas niedriger als der Mittelwert von 0.8 Karat. Der höhere Mittelwert wird sicherlich bedingt durch die vielen Ausreißer nach oben ab 2 bis ca. 5 Karat.
Als nächstes werden Tiefe und Breite untersucht.
fig = px.box(data, y = ['Tiefe', 'Breite'],
title='Diamanten: numerische Eigenschaften',
labels={'variable': 'Eigenschaft', 'value': 'Größe'})
fig.show()
50 % aller Diamanten haben eine Tiefe zwischen 61 % und 62 %. Der Median ist mit 61.8 % mittwig zwischen Q1 und Q3 und stimmt mit dem Mittelwert 61.7 % überein. Es gibt Ausreißer nach oben und unten.
Bei der Breite ist der Median 57 näher am Q1-Wert 56 und und liegt auch etwas unterhalb des Mittelwertes von 57.4.
fig = px.box(data, y = ['x', 'y', 'z'],
title='Diamanten: numerische Eigescnhaften',
labels={'variable': 'Eigenschaft', 'value': 'Wert'})
fig.show()
Der Boxplot sowie die statistischen Kennzahlen der Eigenschaften x, y und z zeigen Ungereimtheiten. Bei allen drei Eigenschaften wird auch der Wert Null angenommen. Das ist unmöglich, daher müssen diese Diamanten aus dem Datensatz entfernt werden.
Darüber hinaus gibt es bei der Größe in y-Richtung zwei deutliche Ausreißer mit 31.8 mm und 58.9 mm. Auch bei der Größe in z-Richtung gibt es einen deutlichen Ausreißer nach oben mit z = 31.8 mm. Diese Diamanten werden ebenfalls entfernt.
data.drop(data[ data['x'] == 0 ].index, inplace=True)
data.drop(data[ data['y'] == 0 ].index, inplace=True)
data.drop(data[ data['z'] == 0 ].index, inplace=True)
data.drop(data[ data['y'] > 31.0 ].index, inplace=True)
data.drop(data[ data['z'] > 31.0 ].index, inplace=True)
data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 53917 entries, 0 to 53939
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Karat 53917 non-null float64
1 Schliffqualitaet 53917 non-null object
2 Farbe 53917 non-null object
3 Reinheit 53917 non-null object
4 Tiefe 53917 non-null float64
5 Breite 53917 non-null float64
6 Preis 53917 non-null int64
7 x 53917 non-null float64
8 y 53917 non-null float64
9 z 53917 non-null float64
dtypes: float64(6), int64(1), object(3)
memory usage: 4.5+ MB
Somit sind es nur 53917 Einträge von ehemals 53940 Einträgen. Es wurden 23 Diamanten entfernt.
Als nächstes betrachten wir die kategorischen Eigenschaften.
for category in input_categorial:
print(f'Eigenschaft {category}: {data[category].unique()}')
Eigenschaft Schliffqualitaet: ['ideal' 'erstklassig' 'gut' 'sehr gut' 'fair']
Eigenschaft Farbe: ['E' 'I' 'J' 'H' 'F' 'G' 'D']
Eigenschaft Reinheit: ['SI2' 'SI1' 'VS1' 'VS2' 'VVS2' 'VVS1' 'I1' 'IF']